"""基础仓库类"""

from typing import TypeVar, Generic, Type, Optional, List, Dict, Any
from sqlalchemy.orm import Session
from sqlalchemy import and_, or_, desc, asc
from app.models.database.base import BaseModel

T = TypeVar('T', bound=BaseModel)


class BaseRepository(Generic[T]):
    """基础仓库类，提供通用的数据库操作"""
    
    def __init__(self, db: Session, model: Type[T]):
        self.db = db
        self.model = model
    
    def create(self, **kwargs) -> T:
        """创建新记录"""
        instance = self.model(**kwargs)
        self.db.add(instance)
        self.db.commit()
        self.db.refresh(instance)
        return instance
    
    def get_by_id(self, id: int) -> Optional[T]:
        """根据ID获取记录"""
        return self.db.query(self.model).filter(self.model.id == id).first()
    
    def get_by_uuid(self, uuid: str) -> Optional[T]:
        """根据UUID获取记录"""
        return self.db.query(self.model).filter(self.model.uuid == uuid).first()
    
    def get_all(self, skip: int = 0, limit: int = 100) -> List[T]:
        """获取所有记录"""
        return self.db.query(self.model).offset(skip).limit(limit).all()
    
    def get_by_filter(self, **filters) -> List[T]:
        """根据过滤条件获取记录"""
        query = self.db.query(self.model)
        for key, value in filters.items():
            if hasattr(self.model, key):
                query = query.filter(getattr(self.model, key) == value)
        return query.all()
    
    def get_one_by_filter(self, **filters) -> Optional[T]:
        """根据过滤条件获取单条记录"""
        query = self.db.query(self.model)
        for key, value in filters.items():
            if hasattr(self.model, key):
                query = query.filter(getattr(self.model, key) == value)
        return query.first()
    
    def update(self, instance: T, **kwargs) -> T:
        """更新记录"""
        for key, value in kwargs.items():
            if hasattr(instance, key):
                setattr(instance, key, value)
        self.db.commit()
        self.db.refresh(instance)
        return instance
    
    def update_by_id(self, id: int, **kwargs) -> Optional[T]:
        """根据ID更新记录"""
        instance = self.get_by_id(id)
        if instance:
            return self.update(instance, **kwargs)
        return None
    
    def delete(self, instance: T) -> bool:
        """删除记录"""
        try:
            self.db.delete(instance)
            self.db.commit()
            return True
        except Exception:
            self.db.rollback()
            return False
    
    def delete_by_id(self, id: int) -> bool:
        """根据ID删除记录"""
        instance = self.get_by_id(id)
        if instance:
            return self.delete(instance)
        return False
    
    def count(self, **filters) -> int:
        """计算记录数量"""
        query = self.db.query(self.model)
        for key, value in filters.items():
            if hasattr(self.model, key):
                query = query.filter(getattr(self.model, key) == value)
        return query.count()
    
    def exists(self, **filters) -> bool:
        """检查记录是否存在"""
        return self.count(**filters) > 0
    
    def get_paginated(self, page: int = 1, page_size: int = 20, **filters) -> Dict[str, Any]:
        """分页获取记录"""
        query = self.db.query(self.model)
        
        # 应用过滤条件
        for key, value in filters.items():
            if hasattr(self.model, key):
                query = query.filter(getattr(self.model, key) == value)
        
        # 计算总数
        total = query.count()
        
        # 计算偏移量
        offset = (page - 1) * page_size
        
        # 获取分页数据
        items = query.offset(offset).limit(page_size).all()
        
        # 计算是否有下一页
        has_next = offset + page_size < total
        
        return {
            "items": items,
            "total": total,
            "page": page,
            "page_size": page_size,
            "has_next": has_next,
            "total_pages": (total + page_size - 1) // page_size
        }
    
    def bulk_create(self, items: List[Dict[str, Any]]) -> List[T]:
        """批量创建记录"""
        instances = [self.model(**item) for item in items]
        self.db.add_all(instances)
        self.db.commit()
        for instance in instances:
            self.db.refresh(instance)
        return instances
    
    def bulk_update(self, updates: List[Dict[str, Any]]) -> bool:
        """批量更新记录"""
        try:
            for update_data in updates:
                id_value = update_data.pop('id', None)
                if id_value:
                    self.db.query(self.model).filter(self.model.id == id_value).update(update_data)
            self.db.commit()
            return True
        except Exception:
            self.db.rollback()
            return False
